#ifndef A_H
#define A_H

#include <stdio.h>
#include <math.h>

#define PI acos(-1)

void swap(double &a, double &b)
{
	double t; 
	t = a;
	a = b;
	b = t;
}

class Fun
{
public:
	virtual double f(double x)
	{
		return 0;
	}
	virtual double df(double x)
	{
		return 0;
	}
};

class EquationSolver
{
public:
	virtual double solve() { return 0; }
};

class Bisection : public EquationSolver
{
private:
	Fun & f;
	double a, b, delta, eps;
	int M;
public:
	Bisection(Fun & _f, double _a, double _b, double _delta, double _eps, int _M):
	f(_f), a(_a), b(_b), delta(_delta), eps(_eps), M(_M) {}
	double solve()
	{
		double h = b - a, c = b, l = a, r = b;
		for (int i = 1; i <= M; i++)
		{
			h = h / 2, c = a + h, l = f.f(a), r = f.f(c);
			if (fabs(h) < delta || fabs(r) < eps)  break;
			else if (l * r > 0)  a = c;
		}
		return c;
	}
};

class Newton : public EquationSolver
{
private:
	Fun & f;
	double a, eps;
	int M;
public:
	Newton(Fun & _f, double _a, double _eps, int _M):
	f(_f), a(_a), eps(_eps), M(_M) {}
	double solve()
	{
		double v, d, b;
		for (int i = 1; i <= M; i++)
		{
			v = f.f(a), d = f.df(a);
			b = a - v / d;
			if (fabs(f.f(b)) < eps)  break;
			a = b;
		}
		return b;
	}
};

class Secant : public EquationSolver
{
private:
	Fun & f;
	double a, b, delta, eps;
	int M;
public:
	Secant(Fun & _f, double _a, double _b, double _delta, double _eps, int _M):
	f(_f), a(_a), b(_b), delta(_delta), eps(_eps), M(_M) {}
	double solve()
	{
		double u = f.f(a), v = f.f(b);
		for (int i = 2; i <= M; i++)
		{
			if (fabs(u) < fabs(v))  swap(a, b), swap(u, v);
			a = b - v * (b - a) / (v - u);
			if (fabs(a - b) < delta || fabs(a) < eps) break;
			u = f.f(a), v = f.f(b);
		}
		return a;
	}
};

#endif